home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 32 / advsys.zip / ADVFCN.C < prev    next >
Text File  |  1987-06-28  |  14KB  |  585 lines

  1. /* advfcn.c - functions for the adventure compiler */
  2. /*
  3.     Copyright (c) 1986, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. #include "advcom.h"
  8. #include "advdbs.h"
  9.  
  10. /* external variables */
  11. extern char aname[];        /* adventure name */
  12. extern int aversion;        /* adventure version number */
  13. extern int cptr;        /* code space pointer */
  14. extern int objbuf[];        /* object staging buffer */
  15. extern int nprops;        /* number of properties in current object */
  16. extern int t_value;        /* token value */
  17. extern char t_token[];        /* token string */
  18. extern char *t_names[];        /* token names */
  19. extern int otable[];        /* object table */
  20. extern int curobj;        /* current object number */
  21. extern int curact;        /* current action offset */
  22. extern int atable[],acnt;    /* action table and count */
  23. extern ARGUMENT *arguments;    /* function argument list */
  24. extern ARGUMENT *temporaries;    /* function temporary variable list */
  25. extern int def_flag;        /* default action flag value */
  26. extern int def_mask;        /* default action mask value */
  27.  
  28. /* external routines */
  29. extern char *malloc();
  30. extern char *save();
  31.  
  32. /* do_adventure - handle the <ADVENTURE name version-number> statement */
  33. do_adventure()
  34. {
  35.     /* get the adventure name */
  36.     frequire(T_IDENTIFIER);
  37.     strncpy(aname,t_token,18);
  38.     aname[18] = 0;
  39.  
  40.     /* get the adventure version number */
  41.     frequire(T_NUMBER);
  42.     aversion = t_value;
  43.  
  44.     /* check for the closing paren */
  45.     frequire(T_CLOSE);
  46. }
  47.  
  48. /* do_word - enter words of a particular type */
  49. do_word(type)
  50. {
  51.     int tkn;
  52.  
  53.     while ((tkn = token()) == T_IDENTIFIER)
  54.     add_word(t_token,type);
  55.     require(tkn,T_CLOSE);
  56. }
  57.  
  58. /* do_synonym - handle the <SYNONYMS ... > statement */
  59. do_synonym()
  60. {
  61.     int tkn,wrd;
  62.  
  63.     frequire(T_IDENTIFIER);
  64.     wrd = add_word(t_token,WT_UNKNOWN);
  65.     while ((tkn = token()) == T_IDENTIFIER)
  66.     add_synonym(t_token,wrd);
  67.     require(tkn,T_CLOSE);
  68. }
  69.  
  70. /* do_define - handle the <DEFINE ... > statement */
  71. do_define()
  72. {
  73.     char name[TKNSIZE+1];
  74.     int tkn;
  75.  
  76.     if ((tkn = token()) == T_OPEN)
  77.     return (do_function());
  78.     stoken(tkn);
  79.  
  80.     while ((tkn = token()) == T_IDENTIFIER) {
  81.     strcpy(name,t_token);
  82.     center(name,getvalue());
  83.     }
  84.     require(tkn,T_CLOSE);
  85. }
  86.  
  87. /* do_variable - handle the <VARIABLE ... > statement */
  88. do_variable()
  89. {
  90.     int tkn;
  91.  
  92.     while ((tkn = token()) == T_IDENTIFIER)
  93.     venter(t_token);
  94.     require(tkn,T_CLOSE);
  95. }
  96.  
  97. /* do_defproperty - handle the <PROPERTY ... > statement */
  98. do_defproperty()
  99. {
  100.     int tkn;
  101.  
  102.     while ((tkn = token()) == T_IDENTIFIER)
  103.     penter(t_token);
  104.     require(tkn,T_CLOSE);
  105. }
  106.  
  107. /* do_default - handle the <DEFAULT ... > statement */
  108. do_default()
  109. {
  110.     int tkn;
  111.  
  112.     /* process statements until end of file */
  113.     while ((tkn = token()) == T_OPEN) {
  114.     frequire(T_IDENTIFIER);
  115.     if (match("actor"))
  116.         do_dflag(A_ACTOR);
  117.     else if (match("direct-object"))
  118.         do_dflag(A_DOBJECT);
  119.     else if (match("indirect-object"))
  120.         do_dflag(A_IOBJECT);
  121.     else
  122.         error("Unknown default definition statement type");
  123.     }
  124.     require(tkn,T_CLOSE);
  125. }
  126.  
  127. /* do_dflag - handle ACTOR, DIRECT-OBJECT, and INDIRECT-OBJECT statements */
  128. do_dflag(flag)
  129.   int flag;
  130. {
  131.     int tkn;
  132.  
  133.     if ((tkn = token()) == T_IDENTIFIER) {
  134.     if (match("required")) {
  135.         def_flag |= flag;
  136.         def_mask &= ~flag;
  137.     }
  138.     else if (match("forbidden")) {
  139.         def_flag &= ~flag;
  140.         def_mask &= ~flag;
  141.     }
  142.     else if (match("optional"))
  143.         def_mask |= flag;
  144.     else
  145.         error("Expecting: REQUIRED, FORBIDDEN or OPTIONAL");
  146.     tkn = token();
  147.     }
  148.     else {
  149.     def_flag |= flag;
  150.     def_mask &= ~flag;
  151.     }
  152.     require(tkn,T_CLOSE);
  153. }
  154.  
  155. /* do_object - handle object (LOCATION,OBJECT,ACTOR) definitions */
  156. int do_object(cname,class)
  157.   char *cname; int class;
  158. {
  159.     int tkn,obj,obase,osize,i,p;
  160.  
  161. printf("[ %s: ",cname);
  162.     frequire(T_IDENTIFIER);
  163. printf("%s ]\n",t_token);
  164.     obj = curobj = oenter(t_token);
  165.  
  166.     /* initialize the object */
  167.     objbuf[O_CLASS/2] = class;
  168.     objbuf[O_NOUNS/2] = NIL;
  169.     objbuf[O_ADJECTIVES/2] = NIL;
  170.     objbuf[O_NPROPERTIES/2] = nprops = 0;
  171.  
  172.     /* copy the property list of the class object */
  173.     if (class) {
  174.     obase = otable[class];
  175.     osize = getword(obase+O_NPROPERTIES);
  176.     for (i = p = 0; i < osize; i++, p += 4)
  177.         if ((getword(obase+O_PROPERTIES+p) & P_CLASS) == 0)
  178.         addprop(getword(obase+O_PROPERTIES+p),0,
  179.                         getword(obase+O_PROPERTIES+p+2));
  180.     }
  181.  
  182.     /* process statements until end of file */
  183.     while ((tkn = token()) == T_OPEN) {
  184.     frequire(T_IDENTIFIER);
  185.     if (match("noun"))
  186.         do_noun();
  187.     else if (match("adjective"))
  188.         do_adjective();
  189.     else if (match("property"))
  190.         do_property(0);
  191.     else if (match("class-property"))
  192.         do_property(P_CLASS);
  193.     else if (match("method"))
  194.         do_method();
  195.     else
  196.         error("Unknown object definition statement type");
  197.     }
  198.     require(tkn,T_CLOSE);
  199.  
  200.     /* copy the object to data memory */
  201.     osize = O_SIZE/2 + nprops*2;
  202.     obase = dalloc(osize*2);
  203.     for (i = p = 0; i < osize; i++, p += 2)
  204.     putword(obase+p,objbuf[i]);
  205.     otable[obj] = obase;
  206.     curobj = NIL;
  207.  
  208.     /* return the object number */
  209.     return (obj);
  210. }
  211.  
  212. /* do_noun - handle the <NOUN ... > statement */
  213. do_noun()
  214. {
  215.     int tkn,new;
  216.  
  217.     while ((tkn = token()) == T_IDENTIFIER) {
  218.     new = dalloc(L_SIZE);
  219.     putword(new+L_DATA,add_word(t_token,WT_NOUN));
  220.     putword(new+L_NEXT,objbuf[O_NOUNS/2]);
  221.     objbuf[O_NOUNS/2] = new;
  222.     }
  223.     require(tkn,T_CLOSE);
  224. }
  225.  
  226. /* do_adjective - handle the <ADJECTIVE ... > statement */
  227. do_adjective()
  228. {
  229.     int tkn,new;
  230.  
  231.     while ((tkn = token()) == T_IDENTIFIER) {
  232.     new = dalloc(L_SIZE);
  233.     putword(new+L_DATA,add_word(t_token,WT_ADJECTIVE));
  234.     putword(new+L_NEXT,objbuf[O_ADJECTIVES/2]);
  235.     objbuf[O_ADJECTIVES/2] = new;
  236.     }
  237.     require(tkn,T_CLOSE);
  238. }
  239.  
  240. /* do_property - handle the <PROPERTY ... > statement */
  241. do_property(flags)
  242.   int flags;
  243. {
  244.     int tkn,name,value;
  245.  
  246.     while ((tkn = token()) == T_IDENTIFIER || tkn == T_NUMBER) {
  247.     name = (tkn == T_IDENTIFIER ? penter(t_token) : t_value);
  248.     value = getvalue();
  249.     setprop(name,flags,value);
  250.     }
  251.     require(tkn,T_CLOSE);
  252. }
  253.  
  254. /* do_method - handle <METHOD (FUN ...) ... > statement */
  255. do_method()
  256. {
  257.     int tkn,name,tcnt;
  258.  
  259.     /* get the property name */
  260.     frequire(T_OPEN);
  261.     frequire(T_IDENTIFIER);
  262. printf("[ method: %s ]\n",t_token);
  263.  
  264.     /* create a new property */
  265.     name = penter(t_token);
  266.  
  267.     /* allocate a new (anonymous) action */
  268.     if (acnt < AMAX)
  269.     ++acnt;
  270.     else
  271.     error("too many actions");
  272.  
  273.     /* store the action as the value of the property */
  274.     setprop(name,P_CLASS,acnt);
  275.  
  276.     /* initialize the action */
  277.     curact = atable[acnt] = dalloc(A_SIZE);
  278.     putword(curact+A_VERBS,NIL);
  279.     putword(curact+A_PREPOSITIONS,NIL);
  280.     arguments = temporaries = NULL;
  281.     tcnt = 0;
  282.  
  283.     /* enter the "self" argument */
  284.     addargument(&arguments,"self");
  285.     addargument(&arguments,"(dummy)");
  286.  
  287.     /* get the argument list */
  288.     while ((tkn = token()) != T_CLOSE) {
  289.     require(tkn,T_IDENTIFIER);
  290.     if (match("&aux"))
  291.         break;
  292.     addargument(&arguments,t_token);
  293.     }
  294.     
  295.     /* check for temporary variable definitions */
  296.     if (tkn == T_IDENTIFIER)
  297.     while ((tkn = token()) != T_CLOSE) {
  298.         require(tkn,T_IDENTIFIER);
  299.         addargument(&temporaries,t_token);
  300.         tcnt++;
  301.     }
  302.  
  303.     /* store the code address */
  304.     putword(curact+A_CODE,cptr);
  305.  
  306.     /* allocate space for temporaries */
  307.     if (temporaries) {
  308.     putcbyte(OP_TSPACE);
  309.     putcbyte(tcnt);
  310.     }
  311.  
  312.     /* compile the code */
  313.     do_code(NULL);
  314.  
  315.     /* free the argument and temporary variable symbol tables */
  316.     freelist(arguments);
  317.     freelist(temporaries);
  318.     arguments = temporaries = NULL;
  319. }
  320.  
  321. /* setprop - set the value of a property */
  322. setprop(prop,flags,value)
  323.   int prop,flags,value;
  324. {
  325.     int i;
  326.  
  327.     /* look for the property */
  328.     for (i = 0; i < nprops; i++)
  329.     if ((objbuf[O_PROPERTIES/2 + i*2] & ~P_CLASS) == prop) {
  330.         objbuf[O_PROPERTIES/2 + i*2 + 1] = value;
  331.         return;
  332.     }
  333.     addprop(prop,flags,value);
  334. }
  335.  
  336. /* addprop - add a property to the current object's property list */
  337. addprop(prop,flags,value)
  338.   int prop,flags,value;
  339. {
  340.     if (nprops >= OPMAX) {
  341.     printf("too many properties for this object\n");
  342.     return;
  343.     }
  344.     objbuf[O_PROPERTIES/2 + nprops*2] = prop|flags;
  345.     objbuf[O_PROPERTIES/2 + nprops*2 + 1] = value;
  346.     objbuf[O_NPROPERTIES/2] = ++nprops;
  347. }
  348.  
  349. /* do_code - compile code for an expression */
  350. int do_code(type)
  351.   char *type;
  352. {
  353.     int adr,tkn;
  354.  
  355.     if (type) printf("[ compiling %s code ]\n",type);
  356.     adr = putcbyte(OP_PUSH);
  357.     while ((tkn = token()) != T_CLOSE) {
  358.     stoken(tkn);
  359.     do_expr();
  360.     }
  361.     putcbyte(OP_RETURN);
  362.     return (adr);
  363. }
  364.  
  365. /* do_action - handle <ACTION ... > statement */
  366. do_action()
  367. {
  368.     int tkn,act;
  369.  
  370.     /* get the action name */
  371.     frequire(T_IDENTIFIER);
  372. printf("[ action: %s ]\n",t_token);
  373.  
  374.     /* create a new action */
  375.     act = aenter(t_token);
  376.     curact = atable[act] = dalloc(A_SIZE);
  377.     putword(curact+A_VERBS,NIL);
  378.     putword(curact+A_PREPOSITIONS,NIL);
  379.     putbyte(curact+A_FLAG,def_flag);
  380.     putbyte(curact+A_MASK,def_mask);
  381.     putword(curact+A_CODE,NIL);
  382.  
  383.     /* process statements until end of file */
  384.     while ((tkn = token()) == T_OPEN) {
  385.     frequire(T_IDENTIFIER);
  386.     if (match("actor"))
  387.         do_flag(A_ACTOR);
  388.     else if (match("verb"))
  389.         do_verb();
  390.     else if (match("direct-object"))
  391.         do_flag(A_DOBJECT);
  392.     else if (match("preposition"))
  393.         do_preposition();
  394.     else if (match("indirect-object"))
  395.         do_flag(A_IOBJECT);
  396.     else if (match("code"))
  397.         putword(curact+A_CODE,do_code(NULL));
  398.     else
  399.         error("Unknown action definition statement type");
  400.     }
  401.     require(tkn,T_CLOSE);
  402. }
  403.  
  404. /* do_flag - handle ACTOR, DIRECT-OBJECT, and INDIRECT-OBJECT statements */
  405. do_flag(flag)
  406.   int flag;
  407. {
  408.     int tkn;
  409.  
  410.     if ((tkn = token()) == T_IDENTIFIER) {
  411.     if (match("required")) {
  412.         putbyte(curact+A_FLAG,getbyte(curact+A_FLAG) | flag);
  413.         putbyte(curact+A_MASK,getbyte(curact+A_MASK) & ~flag);
  414.     }
  415.     else if (match("forbidden")) {
  416.         putbyte(curact+A_FLAG,getbyte(curact+A_FLAG) & ~flag);
  417.         putbyte(curact+A_MASK,getbyte(curact+A_MASK) & ~flag);
  418.     }
  419.     else if (match("optional"))
  420.         putbyte(curact+A_MASK,getbyte(curact+A_MASK) | flag);
  421.     else
  422.         error("Expecting: REQUIRED, FORBIDDEN or OPTIONAL");
  423.     tkn = token();
  424.     }
  425.     else {
  426.     putbyte(curact+A_FLAG,getbyte(curact+A_FLAG) | flag);
  427.     putbyte(curact+A_MASK,getbyte(curact+A_MASK) & ~flag);
  428.     }
  429.     require(tkn,T_CLOSE);
  430. }
  431.  
  432. /* do_verb - handle the <VERB ... > statement */
  433. do_verb()
  434. {
  435.     int tkn,new,lst;
  436.  
  437.     while ((tkn = token()) == T_IDENTIFIER || tkn == T_OPEN) {
  438.     new = dalloc(L_SIZE);
  439.     putword(new+L_NEXT,getword(curact+A_VERBS));
  440.     putword(curact+A_VERBS,new);
  441.     lst = dalloc(L_SIZE);
  442.     putword(lst+L_NEXT,NIL);
  443.     putword(new+L_DATA,lst);
  444.     if (tkn == T_IDENTIFIER)
  445.         putword(lst+L_DATA,add_word(t_token,WT_VERB));
  446.     else {
  447.         if ((tkn = token()) == T_IDENTIFIER)
  448.         putword(lst+L_DATA,add_word(t_token,WT_VERB));
  449.         else
  450.         error("Expecting verb");
  451.         while ((tkn = token()) == T_IDENTIFIER) {
  452.         new = dalloc(L_SIZE);
  453.         putword(new+L_DATA,add_word(t_token,WT_UNKNOWN));
  454.         putword(new+L_NEXT,NIL);
  455.         putword(lst+L_NEXT,new);
  456.         lst = new;
  457.         }
  458.         require(tkn,T_CLOSE);
  459.     }
  460.     }
  461.     require(tkn,T_CLOSE);
  462. }
  463.  
  464. /* do_preposition - handle the <PREPOSITION ... > statement */
  465. do_preposition()
  466. {
  467.     int tkn,new;
  468.  
  469.     while ((tkn = token()) == T_IDENTIFIER) {
  470.     new = dalloc(L_SIZE);
  471.     putword(new+L_DATA,add_word(t_token,WT_PREPOSITION));
  472.     putword(new+L_NEXT,getword(curact+A_PREPOSITIONS));
  473.     putword(curact+A_PREPOSITIONS,new);
  474.     }
  475.     require(tkn,T_CLOSE);
  476. }
  477.  
  478. /* do_function - handle <DEFINE (FUN ...) ... > statement */
  479. do_function()
  480. {
  481.     int tkn,act,tcnt;
  482.  
  483.     /* get the function name */
  484.     frequire(T_IDENTIFIER);
  485. printf("[ function: %s ]\n",t_token);
  486.  
  487.     /* create a new action */
  488.     act = aenter(t_token);
  489.  
  490.     /* initialize the action */
  491.     curact = atable[act] = dalloc(A_SIZE);
  492.     putword(curact+A_VERBS,NIL);
  493.     putword(curact+A_PREPOSITIONS,NIL);
  494.     arguments = temporaries = NULL;
  495.     tcnt = 0;
  496.  
  497.     /* get the argument list */
  498.     while ((tkn = token()) != T_CLOSE) {
  499.     require(tkn,T_IDENTIFIER);
  500.     if (match("&aux"))
  501.         break;
  502.     addargument(&arguments,t_token);
  503.     }
  504.     
  505.     /* check for temporary variable definitions */
  506.     if (tkn == T_IDENTIFIER)
  507.     while ((tkn = token()) != T_CLOSE) {
  508.         require(tkn,T_IDENTIFIER);
  509.         addargument(&temporaries,t_token);
  510.         tcnt++;
  511.     }
  512.  
  513.     /* store the code address */
  514.     putword(curact+A_CODE,cptr);
  515.  
  516.     /* allocate space for temporaries */
  517.     if (temporaries) {
  518.     putcbyte(OP_TSPACE);
  519.     putcbyte(tcnt);
  520.     }
  521.  
  522.     /* compile the code */
  523.     do_code(NULL);
  524.  
  525.     /* free the argument and temporary variable symbol tables */
  526.     freelist(arguments);
  527.     freelist(temporaries);
  528.     arguments = temporaries = NULL;
  529. }
  530.  
  531. /* addargument - add a formal argument */
  532. addargument(list,name)
  533.   ARGUMENT **list; char *name;
  534. {
  535.     ARGUMENT *arg;
  536.     
  537.     if ((arg = (ARGUMENT *)malloc(sizeof(ARGUMENT))) == NULL)
  538.     advfatal("out of memory");
  539.     arg->arg_name = save(name);
  540.     arg->arg_next = *list;
  541.     *list = arg;
  542. }
  543.  
  544. /* freelist - free a list of arguments or temporaries */
  545. freelist(arg)
  546.   ARGUMENT *arg;
  547. {
  548.     ARGUMENT *nxt;
  549.  
  550.     while (arg) {
  551.     nxt = arg->arg_next;
  552.     free(arg->arg_name);
  553.     free(arg);
  554.     arg = nxt;
  555.     }
  556. }
  557.  
  558. /* findarg - find an argument offset */
  559. int findarg(name)
  560.   char *name;
  561. {
  562.     ARGUMENT *arg;
  563.     int n;
  564.     
  565.     for (n = 0, arg = arguments; arg; n++, arg = arg->arg_next)
  566.     if (strcmp(name,arg->arg_name) == 0)
  567.         return (n);
  568.     return (-1);
  569. }
  570.  
  571. /* findtmp - find a temporary variable offset */
  572. int findtmp(name)
  573.   char *name;
  574. {
  575.     ARGUMENT *tmp;
  576.     int n;
  577.  
  578.     for (n = 0, tmp = temporaries; tmp; n++, tmp = tmp->arg_next)
  579.     if (strcmp(name,tmp->arg_name) == 0)
  580.         return (n);
  581.     return (-1);
  582. }
  583.  
  584.           
  585.